# ghostAgents.py
# --------------
# Licensing Information:  You are free to use or extend these projects for
# educational purposes provided that (1) you do not distribute or publish
# solutions, (2) you retain this notice, and (3) you provide clear
# attribution to UC Berkeley, including a link to http://ai.berkeley.edu.
# 
# Attribution Information: The Pacman AI projects were developed at UC Berkeley.
# The core projects and autograders were primarily created by John DeNero
# (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).
# Student side autograding was added by Brad Miller, Nick Hay, and
# Pieter Abbeel (pabbeel@cs.berkeley.edu).


from game import Agent
from game import Actions
from game import Directions
import random
from util import manhattanDistance
import util

class GhostAgent( Agent ):#定义鬼魂Agent的类
    def __init__( self, index ):
        self.index = index

    def getAction( self, state ):#定义鬼魂的行为操作
        dist = self.getDistribution(state)
        if len(dist) == 0:
            return Directions.STOP
        else:
            return util.chooseFromDistribution( dist )

    def getDistribution(self, state):#返回一个计数器，该计数器对所提供状态中操作的分布进行编码。个人理解类似于状态机那种编码
        "Returns a Counter encoding a distribution over actions from the provided state."
        util.raiseNotDefined()

class RandomGhost( GhostAgent ):#分派给鬼魂随机选择合理地有规律的行为
    "A ghost that chooses a legal action uniformly at random."
    def getDistribution( self, state ):
        dist = util.Counter()
        for a in state.getLegalActions( self.index ): dist[a] = 1.0
        dist.normalize()
        return dist

class DirectionalGhost( GhostAgent ):#分配鬼魂的种类，有得选择冲向吃豆人，有的选择逃跑以原理吃豆人
    "A ghost that prefers to rush Pacman, or flee when scared."
    def __init__( self, index, prob_attack=0.8, prob_scaredFlee=0.8 ):
        self.index = index
        self.prob_attack = prob_attack#攻击吃豆人行为
        self.prob_scaredFlee = prob_scaredFlee#害怕远离吃豆人行为

    def getDistribution( self, state ):#符合Agent的问题定义，初始状态、行动集合、转移模型、目标测试函数、路径代价函数
        # Read variables from state
        ghostState = state.getGhostState( self.index )
        legalActions = state.getLegalActions( self.index )
        pos = state.getGhostPosition( self.index )
        isScared = ghostState.scaredTimer > 0

        speed = 1#默认移动速度为1，包括了追击吃豆人的速度
        if isScared: speed = 0.5#如果是害怕吃豆人的种类，逃跑的速度为0.5

        actionVectors = [Actions.directionToVector( a, speed ) for a in legalActions]#三个主要移动特性，移动的向量，到达的新位置，吃豆人的位置
        newPositions = [( pos[0]+a[0], pos[1]+a[1] ) for a in actionVectors]
        pacmanPosition = state.getPacmanPosition()

        # Select best actions given the state       由现在所处的状态，选择鬼魂所应该采取的最佳行为
        distancesToPacman = [manhattanDistance( pos, pacmanPosition ) for pos in newPositions]
        if isScared:
            bestScore = max( distancesToPacman )#根据距离进行评分，由评分来进行决定所应该采取的行为。这个评分系统和五子棋评分系统类似。进行相应的搜索
            bestProb = self.prob_scaredFlee#如果是害怕吃豆人的鬼魂，越远越好，否则越近越好，相应地采取攻击或者逃跑的行为
        else:
            bestScore = min( distancesToPacman )
            bestProb = self.prob_attack
        bestActions = [action for action, distance in zip( legalActions, distancesToPacman ) if distance == bestScore]

        # Construct distribution
        dist = util.Counter()
        for a in bestActions: dist[a] = bestProb / len(bestActions)
        for a in legalActions: dist[a] += ( 1-bestProb ) / len(legalActions)
        dist.normalize()
        return dist
